"use strict";

import Vue from 'vue';
import axios from "axios";

/**
 *  npm install --save axios vue-cookies
 */
import VueCookies from 'vue-cookies'

Vue.use(VueCookies);


let config = {
    timeout: 20 * 60 * 1000, // Timeout 20min
    /* 让axios能使用session */
    withCredentials: true, //意思是携带cookie信息,保持session的一致性
    baseURL: "/api"
};

const _axios = axios.create(config);


/* 取消调用链必须使用 CancelToken*/
const CancelToken = axios.CancelToken;

_axios.interceptors.request.use(
    function (config) {
        /**
         * source 方法是CancelToken的一个工厂方法
         * CancelToken.source = function source() {
         *      var cancel;
         *      var token = new CancelToken(function executor(c) {
         *          cancel = c;
         *      });
         *
         *      return {
         *          token: token,
         *          cancel: cancel
         *      };
         * };
         * @type {CancelTokenSource}
         */
        /** source == {
         *               token: token,
         *               cancel: cancel
         *            }
         */
        const source = CancelToken.source();

        /**
         * 全局添加cancelToken
         * 建立一个全局变量用于保存未完成的请求列表
         * 当跳转到新页面，取消这些未完成的请求
         */

        /**
         * 因为post需要cancelToken参数
         * axios.post('/user/12345', {//post请求在第三个参数
         *            name: 'new name'
         *           }, {
         *            cancelToken: source.token
         *          });
         * @type {CancelToken}
         */
        config.cancelToken = source.token; // 因为post需要cancelToken参数

        /**
         * 全局保存请求，在router跳转页面的时候，全部取消
         * if(!a) { a = [] }
         * 等价于 a = ( a || [])
         * 等价于 a = a || []
         */
        Vue.prototype.__axiosPromiseRequestArray = ( Vue.prototype.__axiosPromiseRequestArray || [] );
        Vue.prototype.__axiosPromiseRequestArray.push(source.cancel);

        return config;
    },
    function (error) {
        // Do something with request error
        return Promise.reject(error);
    }
);

// Add a response interceptor
_axios.interceptors.response.use(
    /**
     * 非异常情况下调用此方法
     * @param response
     * @returns {AxiosResponse<any>}
     */
    function (response) {
        //let url = response.config.url;
        //console.log("response from url: %s", url);
        //let headers = response.headers;
        //console.log("headers: %s", JSON.stringify(headers));

        //et JSESSIONID = VueCookies.get('JSESSIONID');
        //console.log("JSESSIONID: %s", JSESSIONID);

        let operationResult = response.data;
        if (!operationResult) {
            throw new Error("NO DATA");
        }

        /**
         * 返回验证码时，是直接使用render方法，没有使用统一的ResultAssistor,所以需要判断是否存在operationResult.isOK
         * 如果不存在，就直接返回内容
         */
        if (operationResult.isOK != undefined && operationResult.isOK === false) {
            throw new Error(JSON.stringify(operationResult)); // 直接进入api方法的.catch(function(error) {}); 不会走拦截器error => {...}
        }

        return response;
    },
    /**
     * 不等于200 都走下面代码
     * @param error
     * @returns {Promise<never>|Promise<any>}
     */
    function (error) { /* onRejected */
        // Do something with response error
        if (axios.isCancel(error)) {
            console.log('Request canceled %s', error.message);
            /* 取消的情况下，终端Promise调用链 */
            return new Promise(() => {});
        }

        let msg = "";
        /* 进入此处，会在浏览器控制台提示错误 */
        let response = error.response;
        if(!response) {
            console.log("No response");
            return Promise.reject(error);
        }

        /**
         * 401 该HTTP状态码表示认证错误，
         * 表示这个请求没有被服务器认证或者客户端传送的证书错误，
         * 服务端在权限过滤器中鉴权失败
         */
        if (response.status === 401) {
            const source = CancelToken.source();
            source.cancel(); // 取消所有请求
            window.localStorage.clear();
            console.log("Need Login");
            return Promise.reject(error);
        }
        /**
         * 403 Forbidden : 该HTTP状态码关于授权的，跟应用的的逻辑有关，表示客户端没有权限去访问要求资源
         */
        else if (response.status === 403) {
            msg = response.status + ", 所请求的资源无访问权限";
        } else if (response.status === 500) {
            msg = response.status + ", 所请求的资源发生错误";
        } else {
            msg = response.status + ", 其他错误";
        }


        console.log(msg);

        return Promise.reject(error);
    }
);

Plugin.install = function (Vue) {
    Vue.axios = _axios;
    window.axios = _axios;
    Object.defineProperties(Vue.prototype, {
        axios: {
            get() {
                return _axios;
            }
        },
        $axios: {
            get() {
                return _axios;
            }
        },
    });
};

Vue.use(Plugin)

export default Plugin;